#include "scene.h"
#include <algorithm>
#include <iostream>
void SceneNode::attachChild(Ptr child)
{
	child->mParent = this;
	mChildren.push_back(std::move(child));
}

SceneNode::Ptr SceneNode::detachChild(const SceneNode & node)
{
	auto found = std::find_if(mChildren.begin(), mChildren.end(),
		[&](Ptr& p) -> bool {return p.get() == &node; });
	assert(found != mChildren.end());
	Ptr result = std::move(*found);
	result->mParent = nullptr;
	mChildren.erase(found);
	return result;
}

void SceneNode::update(sf::Time dt)
{
	updateCurrent(dt);
	updateChildren(dt);
}

sf::Transform SceneNode::getGlobalTransform() const
{
	sf::Transform res = getTransform();
	for (SceneNode* node = mParent; node != nullptr; node = node->mParent) {
		res *= node->getTransform();
	}
	return res;
}

sf::Vector2f SceneNode::getWordPosition() const
{
	return getGlobalTransform() * getPosition();
}

unsigned int SceneNode::getCategory() const
{
	return mCategory;
}

void SceneNode::onCommand(const Command & command, sf::Time dt)
{
	if (mCategory & command.category) {
		command.action(*this, dt);
	}
	FOREACH(auto & child, mChildren) {
		child->onCommand(command, dt);
	}
}

void SceneNode::updateChildren(sf::Time dt)
{
	FOREACH(auto& child, mChildren) {
		child->update(dt);
	}
}

void SceneNode::drawCurrent(sf::RenderTarget & target, sf::RenderStates states) const
{
}

void SceneNode::updateCurrent(sf::Time dt)
{
	
}

void SceneNode::draw(sf::RenderTarget & target, sf::RenderStates states) const
{
	states.transform *= getTransform();

	drawCurrent(target, states);

	FOREACH(const auto& child, mChildren) {
		child->draw(target, states);
	}
}

SpriteNode::SpriteNode(const sf::Texture & texture)
	:mSprite(texture)
{
}

SpriteNode::SpriteNode(const sf::Texture & texture, const sf::IntRect & rect)
	:mSprite(texture)
{
	mSprite.setTextureRect(rect);
}

void SpriteNode::drawCurrent(sf::RenderTarget & target, sf::RenderStates states) const
{
	target.draw(mSprite);
}
